/**

This file is part of MaCI/GIMnet.

MaCI/GIMnet is free software: you can redistribute it and/or modify it 
under the terms of the GNU Lesser General Public License as published 
by the Free Software Foundation, either version 3 of the License, or 
(at your option) any later version.

MaCI/GIMnet is distributed in the hope that it will be useful, but WITHOUT 
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 
FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public 
License for more details.

You should have received a copy of the GNU Lesser General Public 
License along with GIMnet. (See COPYING.LESSER) If not, see 
<http://www.gnu.org/licenses/>.

**/
#include "JoystickControlEvent.h"

DEFINE_EVENT_TYPE(wxEVT_GIMUI_JOYSTICK_MOVE)
DEFINE_EVENT_TYPE(wxEVT_GIMUI_JOYSTICK_BUTTON_UP)
DEFINE_EVENT_TYPE(wxEVT_GIMUI_JOYSTICK_BUTTON_DOWN)

AxisInfo::AxisInfo(const int pos)
  : position (pos),
    inversion (false)
{}

JoystickStatus::JoystickStatus(const int nAxes /* = 0 */,
                               const int nButtons /* = 0 */)
  : readable (false),
    numberOfAxes (nAxes),
    numberOfButtons (nButtons),
    buttons (0),
    axes (nAxes, 0)
{}

JoystickStatus::~JoystickStatus()
{}

float JoystickStatus::getPosition(int axisNumber) const
{
  return (axes[axisNumber]).position;
}

bool JoystickStatus::getInversion(int axisNumber) const
{
  return (axes[axisNumber]).inversion;
}

bool JoystickStatus::getSingleButtonState(const int buttonNumber) const
{
  bool currentStatus = false;
  // Shift correct button to first.
  int currentButtons = getButtonState() >> buttonNumber;
  // Find out if it is 1 or 0;
  currentStatus = currentButtons & 1;

  return currentStatus;
}

/* No support for axis inversion, do not use
bool JoystickStatus::setPosition(const int axisNumber,
                                 const float axisValue)
{
  (axes[axisNumber]).position = axisValue;
  return true;
}
*/

bool JoystickStatus::setInversion(const int axisNumber,
                                  const bool invert)
{
  (axes[axisNumber]).inversion = invert;
  return true;
}

int JoystickStatus::compareToAxis(const int axisNumber,
                                  const float axisValue)
{
  float oldValue = axes.at(axisNumber).position;
  float newValue;
  if (axes[axisNumber].inversion) { // Invert axis
    newValue = -axisValue;
  } else {
    newValue = axisValue;
  }
  
  if (oldValue != newValue) {
    (axes[axisNumber]).position = newValue;
    return JOYSTICKCONTROL_STATUS_CHANGED;
  } else {
    return JOYSTICKCONTROL_STATUS_UNCHANGED;
  }
}

int JoystickStatus::compareToButtons(const int buttonState)
{
  int diff = buttonState ^ buttons;
  if (diff) {
    buttons = buttonState;
  }
  return diff;
}

IMPLEMENT_DYNAMIC_CLASS(GIMUIJoystickEvent, wxEvent)

GIMUIJoystickEvent::GIMUIJoystickEvent(int id /* = 0 */,
                                       wxEventType commandType /* = wxEVT_NULL */)
  : wxEvent (id, commandType),
    currentStatus (),
    changeId (),
    joystickId ()
{}

GIMUIJoystickEvent::GIMUIJoystickEvent(const GIMUIJoystickEvent &original)
  : wxEvent (original),
    currentStatus (original.currentStatus),
    changeId (original.changeId),
    joystickId (original.joystickId)
{}

GIMUIJoystickEvent::GIMUIJoystickEvent(wxEventType commandType,
                                       const JoystickStatus &joyStatus)
  : wxEvent(0, commandType),
    currentStatus (joyStatus),
    changeId (),
    joystickId ()
{}
